#include "Defines.h"
#include "Common.h"
#include "Config.h"

const int REF_PIXEL_MAP_MATRIX[REF_PIXEL_NUMBER][2] = {
	{-3, -2}, {-1, -2}, { 1, -2}, { 3, -2},
	{ 3, -1}, { 3,  0}, { 3,  1}, { 3,  2},
	{ 1,  2}, {-1,  2}, {-3,  2}, {-3,  1},
	{-3,  0}, {-3, -1}, {-1, -1}, { 1, -1},
	{ 1,  0}, { 1,  1}, {-1,  1}, {-1,  0} 
};

bool GetRefPixelArray( int x, int y, unsigned char * ref_pixel_array, unsigned char * frame, int width, int height )
{

	for( int i=0; i<REF_PIXEL_NUMBER; i++ )
	{
		ref_pixel_array[i] = frame[ (y+REF_PIXEL_MAP_MATRIX[i][1]) * width + x+REF_PIXEL_MAP_MATRIX[i][0] ];
	}

	return true;
}

//void Interpolate()
//{
//	CConfig * config = CConfig::GetConfig();
//	CPatternList * pattern_list = CPatternList::GetInstance();
//
//	// Interpolate Border Area
//
//	// TODO skip border now
//
//
//	// Interpolate Inner Area
//	vector<CPattern*>::iterator pattern_iter = pattern_list->m_pvecPattern->begin();
//	vector<CPos>::iterator pos_iter;
//	unsigned char ref_pixel_array[20];
//	unsigned char inter_pixel = 0;
//	unsigned char frame_no;
//	int width = config->seq->m_iWidth;
//	int height = config->seq->m_iHeight;
//	int x;
//	int y;
//	vector<CPos> * pos_list = NULL;
//
//
//	// Patterned Area
//	for ( ; pattern_iter!=pattern_list->m_pvecPattern->end(); pattern_iter++ )
//	{
//		(*pattern_iter)->DoInterplate();
//	}
//
//	// UnPattern Area
//	pos_list = pattern_list->m_pvecUnpattern;
//	for ( pos_iter = pos_list->begin(); pos_iter!=pos_list->end(); pos_iter++ )
//	{
//		frame_no = (*pos_iter).m_ucFrame;
//		x = (*pos_iter).m_usX;
//		y = (*pos_iter).m_usY;
//
//		GetRefPixelArray( x, y, ref_pixel_array, config->seq->m_ppRecPixelArray[frame_no], width, height );
//		inter_pixel = ComputeInterpolationPixel( ref_pixel_array, pattern_list->m_caCoff );
//		config->seq->m_ppIntPixelArray[frame_no][y * width + x] = inter_pixel;
//	}
//
//}

unsigned char ComputeInterpolationPixel( unsigned char * ref_pixel_array, char * coff_array )
{
	int result = 0;
	int factor = 0;
	for ( int i=0; i<REF_PIXEL_NUMBER; i++ )
	{
		result += coff_array[i] * ref_pixel_array[i];
		factor += coff_array[i];
	}

	result = (result+factor/2) / factor;

	if ( result < 0 ) result = 0;
	if ( result > 255 ) result = 255;

	return static_cast<unsigned char>( result );
}



bool PatternIntToArray( unsigned int pattern, char * pattern_array )
{
	for ( int i=0; i<REF_PIXEL_NUMBER; i++ )
	{
		pattern_array[REF_PIXEL_NUMBER-i-1] = ( (pattern&(1<<i)) == 0? 0:1 );
	}

	return true;
}

unsigned int PatternArrayToInt( char * pattern_array )
{
	unsigned int pattern = 0;
	for ( int i=0; i<REF_PIXEL_NUMBER; i++ )
	{
		pattern += pattern_array[REF_PIXEL_NUMBER-i-1] * (1<<i);
	}

	return pattern;
}


bool BinarizeRefPixelArray( char * pattern_array, unsigned char * ref_pixel_array )
{
	int sum = 0;
	int count = 0;
	unsigned int pattern_mask = CConfig::GetConfig()->pattern_mask;
	for ( int i=0; i<REF_PIXEL_NUMBER; i++ )
	{
		if ( GetPatternBit( pattern_mask, i ) != 0 )
		{
			sum += ref_pixel_array[i];
			count++;
		}
	}
	sum = sum/count;

	for ( int i=0; i<REF_PIXEL_NUMBER; i++ )
	{
		if ( GetPatternBit( pattern_mask, i ) != 0 )
		{
			pattern_array[i] = (ref_pixel_array[i] > sum)? 1:0;
		}
		else
		{
			pattern_array[i] = 0;
		}
	}

	return true;
}

unsigned int GetPatternBit( unsigned int pattern, int i )
{
	return pattern & (1<<(REF_PIXEL_NUMBER-1-i));
}

bool CheckAreaFlat( unsigned char * ref_pixel_array )
{
	// TODO: mask?
	int max = 0;
	int min = 256;

	for ( int i=0; i<REF_PIXEL_NUMBER; i++ )
	{
		if ( max < ref_pixel_array[i] ) max = ref_pixel_array[i];
		if ( min > ref_pixel_array[i] ) min = ref_pixel_array[i];
	}

	if ( max - min < FLAT_THRESHOLD_VALUE ) 
	{
		return true;
	}
	else
	{
		return false;
	}
}